﻿using System;
using System.ComponentModel;
using System.Collections.Specialized;
using System.Data;
using System.Text;
using System.Text.RegularExpressions;
using System.Web.UI;
using System.Web.UI.WebControls;


namespace GONES.Tools.Web
{
    [DefaultProperty("PageSize")]
    [DefaultEvent("PageChanged")]
    [ParseChildren(false)]
    [PersistChildren(false)]
    [ToolboxData("<{0}:Paging runat=server></{0}:Paging>")]
    public class Paging : Panel, INamingContainer, IPostBackEventHandler, IPostBackDataHandler
    {
        #region Properties
        private string m_statinfotext = "共 %RecordCount% 条记录，%CurrentPageIndex% / %PageCount% 页";
        /// <summary>
        /// 自定义汇总内容
        /// </summary>
        public string StatinfoText
        {
            get { return this.m_statinfotext; }
            set { this.m_statinfotext = value; }
        }

        bool _showsuminfo = true;
        /// <summary>
        /// 是否显示汇总信息
        /// </summary>
        public bool ShowSuminfo
        {
            get { return this._showsuminfo; }
            set { this._showsuminfo = value; }
        }

        /// <summary>
        /// 记录总数
        /// </summary>
        public long RecordCount
        {
            get
            {
                object obj = ViewState["Recordcount"];
                return (obj == null) ? 0 : (long)obj;
            }
            set
            {
                ViewState["Recordcount"] = value;
            }
        }

        /// <summary>
        /// 当前页的页码
        /// </summary>
        public int PageIndex
        {
            get
            {
                object cpage = ViewState["CurrentPageIndex"];
                int pindex = (cpage == null) ? 1 : (int)cpage;
                if (pindex > this.PageCount && this.PageCount > 0)
                    return this.PageCount;
                else if (pindex < 1)
                    return 1;
                return pindex;
            }
            set
            {
                int cpage = value;
                if (cpage < 1)
                    cpage = 1;
                else if (cpage > PageCount)
                    cpage = this.PageCount;
                ViewState["CurrentPageIndex"] = cpage;
            }
        }

        /// <summary>
        /// 总页数量
        /// </summary>
        public int PageCount
        {
            get
            {
                if (this.RecordCount == 0)
                    return 1;
                return (int)Math.Ceiling((double)this.RecordCount / (double)this.PageSize);
            }
        }

        /// <summary>
        /// 每页记录集的起始数字
        /// </summary>
        public int RecordindexBegin
        {
            get
            {
                int _recordindexbegin = (this.PageIndex - 1) * this.PageSize + 1;

                if (_recordindexbegin < 0)
                {
                    _recordindexbegin = 0;
                }

                return _recordindexbegin;
            }
        }

        //Int32 _recordindexend = 0;
        /// <summary>
        /// 每页记录集的末尾数字
        /// </summary>
        public long RecordindexEnd
        {
            get
            {
                long _recordindexend = this.PageIndex * this.PageSize;
                if (_recordindexend > this.RecordCount)
                {
                    _recordindexend = this.RecordCount;
                }

                return _recordindexend;
            }
        }

        int m_pagesize = 20;
        /// <summary>
        /// 每页显示的记录数
        /// </summary>
        public int PageSize
        {
            get { return this.m_pagesize; }
            set { this.m_pagesize = value; }
        }


        PageIndexBox _pageindexbox = PageIndexBox.Auto;
        /// <summary>
        /// 是否显示页索引框
        /// </summary>
        public PageIndexBox @PageIndexBox
        {
            get { return this._pageindexbox; }
            set { this._pageindexbox = value; }
        }

        PageIndexButton _pageindexbutton = PageIndexButton.Button;
        /// <summary>
        /// 跳转页面按钮类型
        /// </summary>
        public PageIndexButton @PageIndexButton
        {
            get { return this._pageindexbutton; }
            set { this._pageindexbutton = value; }
        }

        private string m_btnimgurl = "";
        /// <summary>
        /// 按钮图片URL
        /// </summary>
        public string ButtonImgurl
        {
            get { return this.m_btnimgurl; }
            set { this.m_btnimgurl = value; }
        }

        PageLayout _pagelayout = PageLayout.Table;
        /// <summary>
        /// 显示方式
        /// </summary>
        public PageLayout @PageLayout
        {
            get { return this._pagelayout; }
            set { this._pagelayout = value; }
        }

        private bool m_shownumber = true;
        public bool ShowNumeric
        {
            get { return this.m_shownumber; }
            set { this.m_shownumber = value; }
        }

        private byte m_numericcount = 5;
        public byte NumericCount
        {
            get { return this.m_numericcount; }
            set { this.m_numericcount = value; }
        }
        #endregion


        private string inputPageIndex;
        private static readonly object EventPageChanging = new object();
        private static readonly object EventPageChanged = new object();
        //private bool pageChangeEventHandled = false;

        /// <summary>
        /// 页面载入
        /// </summary>
        /// <param name="e"></param>
        protected override void OnLoad(EventArgs e)
        {
            if ((this.PageIndexBox == PageIndexBox.Always) || (this.PageIndexBox == PageIndexBox.Auto && this.PageCount > 1))
            {
                inputPageIndex = Page.Request.Form[UniqueID + "_input"];
            }

            base.OnLoad(e);

        }

        /// <summary>
        /// 重写PreRender事件
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPreRender(EventArgs e)
        {
            if (this.PageCount > 1)
            {
                if ((this.PageIndexBox == PageIndexBox.Always) || (this.PageIndexBox == PageIndexBox.Auto && this.PageCount > 1))
                {
                    StringBuilder sb = new StringBuilder("<script language=\"Javascript\">\n");

                    sb.Append("function DigitalInput()\n");
                    sb.Append("{\n");
                    sb.Append("	var keys=\"48,49,50,51,52,53,54,55,56,57\";\n\n");
                    sb.Append("	if(keys.indexOf(window.event.keyCode)<0)\n");
                    sb.Append("		window.event.keyCode = 0;\n");
                    sb.Append("}\n\n");

                    sb.Append("function GoPage(boxEl, pageCount)\n");
                    sb.Append("{\n");
                    sb.Append("	var pageIndex = document.getElementById(boxEl).value;\n\n");
                    sb.Append("	if(pageIndex==\"\")\n");
                    sb.Append("	{\n");
                    sb.Append("		alert(\"请输入数字！\");\n");
                    sb.Append("		return false;\n");
                    sb.Append("	}\n\n");
                    sb.Append("	if(pageIndex>pageCount)\n");
                    sb.Append("	{\n");
                    sb.Append("		alert(\"输入数字不能超过\"+ pageCount +\"！\");\n");
                    sb.Append("		return false;\n");
                    sb.Append("	}\n");
                    sb.Append("}\n");

                    sb.Append("\n</script>");
                    Type ctype = GetType();
                    ClientScriptManager cs = Page.ClientScript;
                    if (!cs.IsClientScriptBlockRegistered(ctype, "anp_script"))
                        cs.RegisterClientScriptBlock(ctype, "anp_script", sb.ToString());
                }
            }
            base.OnPreRender(e);
        }

        /// <summary>
        /// 重写开始标记
        /// </summary>
        /// <param name="writer"></param>
        public override void RenderBeginTag(HtmlTextWriter writer)
        {
            writer.Write("<!-- 分页开始 -->");
            writer.WriteLine();
        }

        /// <summary>
        /// 重写结束标记
        /// </summary>
        /// <param name="writer"></param>
        public override void RenderEndTag(HtmlTextWriter writer)
        {
            writer.WriteLine();
            writer.Write("<!-- 分页结束 -->");
        }

        /// <summary>
        /// 生成统计文字
        /// </summary>
        /// <returns></returns>
        private void CreateLeftInfo(HtmlTextWriter writer)
        {
            string origText = this.StatinfoText;

            if (!string.IsNullOrEmpty(origText) && origText.IndexOf('%') >= 0)
            {
                string[] props = new string[] { "recordcount", "pagecount", "currentpageindex", "startrecordindex", "endrecordindex", "pagesize" };
                StringBuilder sb = new StringBuilder(origText);
                Regex reg = new Regex("(?<ph>%(?<pname>\\w{8,})%)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
                MatchCollection mts = reg.Matches(origText);
                foreach (Match m in mts)
                {
                    string p = m.Groups["pname"].Value.ToLower();
                    if (Array.IndexOf(props, p) >= 0)
                    {
                        string repValue = null;
                        switch (p)
                        {
                            case "recordcount":
                                repValue = this.RecordCount.ToString();
                                break;
                            case "pagecount":
                                repValue = this.PageCount.ToString();
                                break;
                            case "currentpageindex":
                                repValue = this.PageIndex.ToString();
                                break;
                            case "startrecordindex":
                                repValue = this.RecordindexBegin.ToString();
                                break;
                            case "endrecordindex":
                                repValue = this.RecordindexEnd.ToString();
                                break;
                            case "pagesize":
                                repValue = this.PageSize.ToString();
                                break;
                            //case "pagesremain":
                            //    repValue = PagesRemain.ToString();
                            //    break;
                            //case "recordsremain":
                            //    repValue = RecordsRemain.ToString();
                            //    break;
                        }
                        if (repValue != null)
                            sb.Replace(m.Groups["ph"].Value, repValue);
                    }
                }
                writer.Write(sb.ToString());
            }
            else
            {
                writer.Write(origText);
            }
        }

        private string GetHrefString(int pageIndex)
        {
            return Page.ClientScript.GetPostBackClientHyperlink(this, pageIndex.ToString());
        }

        /// <summary>
        /// 生成分页右边文字
        /// </summary>
        /// <returns></returns>
        private void CreateRightInfo(HtmlTextWriter writer)
        {
            if (this.PageIndex > 1)
            {
                writer.AddAttribute(HtmlTextWriterAttribute.Href, GetHrefString(1));
                writer.RenderBeginTag(HtmlTextWriterTag.A);
                writer.Write("首页");
                writer.RenderEndTag();

                writer.Write("&nbsp;");

                writer.AddAttribute(HtmlTextWriterAttribute.Href, GetHrefString(this.PageIndex - 1));
                writer.RenderBeginTag(HtmlTextWriterTag.A);
                writer.Write("上一页");
                writer.RenderEndTag();

                writer.Write("&nbsp;");
            }
            else
            {
                writer.Write("<span style=\"color:#999\">首页&nbsp;上一页</span>&nbsp;");
            }

            if (this.ShowNumeric)
            {
                int PageindexBegin = ((this.PageIndex - 1) / this.NumericCount) * this.NumericCount;
                if (this.PageCount > this.NumericCount)
                {
                    int startOffset = this.PageIndex - (int)(Math.Ceiling((double)this.NumericCount / 2));
                    if (startOffset > 0)
                    {
                        PageindexBegin = startOffset;
                        if (PageindexBegin > (PageCount - this.NumericCount))
                            PageindexBegin = PageCount - this.NumericCount;
                    }
                }

                int PageindexEnd = ((PageindexBegin + this.NumericCount) > this.PageCount) ? this.PageCount : (PageindexBegin + this.NumericCount);

                if (PageindexBegin >= 1)
                {
                    //writer.Write("&nbsp;");

                    writer.AddAttribute(HtmlTextWriterAttribute.Href, GetHrefString(PageindexBegin));
                    writer.RenderBeginTag(HtmlTextWriterTag.A);
                    writer.Write("...");
                    writer.RenderEndTag();

                    writer.Write("&nbsp;");
                }

                for (int i = PageindexBegin + 1; i <= PageindexEnd; i++)
                {
                    if (i == this.PageIndex)
                    {
                        writer.Write("<font style=\"background:#f60; padding:2px; color:white\">" + i + "</font>&nbsp;");
                    }
                    else
                    {
                        writer.AddAttribute(HtmlTextWriterAttribute.Href, GetHrefString(i));
                        writer.RenderBeginTag(HtmlTextWriterTag.A);
                        writer.Write(i.ToString());
                        writer.RenderEndTag();

                        writer.Write("&nbsp;");
                    }
                }


                if (PageindexEnd < this.PageCount)
                {
                    writer.AddAttribute(HtmlTextWriterAttribute.Href, GetHrefString(PageindexEnd+1));
                    writer.RenderBeginTag(HtmlTextWriterTag.A);
                    writer.Write("...");
                    writer.RenderEndTag();

                    writer.Write("&nbsp;");
                }
            }
            else
            {
                writer.Write("&nbsp;&nbsp;");
            }

            if (this.PageIndex < this.PageCount)
            {
                writer.AddAttribute(HtmlTextWriterAttribute.Href, GetHrefString(this.PageIndex + 1));
                writer.RenderBeginTag(HtmlTextWriterTag.A);
                writer.Write("下一页");
                writer.RenderEndTag();

                writer.Write("&nbsp;");

                writer.AddAttribute(HtmlTextWriterAttribute.Href, GetHrefString(this.PageCount));
                writer.RenderBeginTag(HtmlTextWriterTag.A);
                writer.Write("末页");
                writer.RenderEndTag();
            }
            else
            {
                writer.Write("<span style=\"color:#999\">下一页&nbsp;末页</span>");
            }


            if ((this.PageIndexBox == PageIndexBox.Always) || (this.PageIndexBox == PageIndexBox.Auto && this.PageCount > 1))
            {
                string boxClientId = UniqueID + "_input";
                writer.Write("&nbsp;&nbsp;到第&nbsp;");

                writer.AddAttribute(HtmlTextWriterAttribute.Type, "text");
                writer.AddStyleAttribute(HtmlTextWriterStyle.Width, "30px");
                writer.AddStyleAttribute(HtmlTextWriterStyle.Height, "16px");
                writer.AddAttribute(HtmlTextWriterAttribute.Value, "");
                //if (!string.IsNullOrEmpty(PageIndexBoxStyle))
                //    writer.AddAttribute(HtmlTextWriterAttribute.Style, PageIndexBoxStyle);
                //if (!string.IsNullOrEmpty(PageIndexBoxClass))
                //    writer.AddAttribute(HtmlTextWriterAttribute.Class, PageIndexBoxClass);
                //if (!Enabled || (PageCount <= 1 && AlwaysShow))
                //    writer.AddAttribute(HtmlTextWriterAttribute.Disabled, "disabled");
                writer.AddAttribute(HtmlTextWriterAttribute.Name, boxClientId);
                writer.AddAttribute(HtmlTextWriterAttribute.Id, boxClientId);
                //string chkInputScript = "ANP_checkInput(\'" + boxClientId + "\'," + PageCount + ")";
                //string keydownScript = "ANP_keydown(event,\'" + UniqueID + "_btn\');";
                //string clickScript = "if(" + chkInputScript + "){ANP_goToPage(document.getElementById(\'" + boxClientId + "\'));}";

                writer.AddAttribute("onkeypress", "return DigitalInput()");
                writer.RenderBeginTag(HtmlTextWriterTag.Input);
                writer.RenderEndTag();
                //Text after page index box
                //if (!string.IsNullOrEmpty(TextAfterPageIndexBox))
                //    writer.Write(TextAfterPageIndexBox);
                writer.Write("&nbsp;页&nbsp;");

                //button
                writer.AddAttribute(HtmlTextWriterAttribute.Type, "Submit");
                writer.AddAttribute(HtmlTextWriterAttribute.Name, UniqueID);
                writer.AddAttribute(HtmlTextWriterAttribute.Id, UniqueID + "_btn");
                writer.AddAttribute(HtmlTextWriterAttribute.Value, "确定");
                //if (!string.IsNullOrEmpty(SubmitButtonClass))
                //    writer.AddAttribute(HtmlTextWriterAttribute.Class, SubmitButtonClass);
                //if (!string.IsNullOrEmpty(SubmitButtonStyle))
                //    writer.AddAttribute(HtmlTextWriterAttribute.Style, SubmitButtonStyle);
                //if (!Enabled || (PageCount <= 1 && AlwaysShow))
                //    writer.AddAttribute(HtmlTextWriterAttribute.Disabled, "disabled");
                writer.AddAttribute(HtmlTextWriterAttribute.Onclick, "return GoPage(\'" + boxClientId + "\'," + PageCount + ")");
                writer.RenderBeginTag(HtmlTextWriterTag.Input);
                writer.RenderEndTag();

            }
        }

        protected override void RenderContents(HtmlTextWriter output)
        {
            output.AddAttribute(HtmlTextWriterAttribute.Id, this.ID);
            if (!string.IsNullOrEmpty(this.CssClass))
            {
                output.AddAttribute(HtmlTextWriterAttribute.Class, this.CssClass);
            }
            if (!string.IsNullOrEmpty(this.Width.ToString()))
            {
                output.AddAttribute(HtmlTextWriterAttribute.Width, this.Width.ToString());
            }
            if (!string.IsNullOrEmpty(this.HorizontalAlign.ToString()))
            {
                output.AddAttribute(HtmlTextWriterAttribute.Align, this.HorizontalAlign.ToString());
            }


            if (this.PageLayout == PageLayout.Div)
            {
                output.RenderBeginTag(HtmlTextWriterTag.Div);
                if (this.ShowSuminfo)
                {
                    CreateLeftInfo(output);
                    output.Write("&nbsp;&nbsp;");
                }
                CreateRightInfo(output);

                output.RenderEndTag();
            }
            else
            {
                output.AddAttribute(HtmlTextWriterAttribute.Width, "100%");  // by bndy at 2008/07/12 10:47

                output.RenderBeginTag(HtmlTextWriterTag.Table);
                output.RenderBeginTag(HtmlTextWriterTag.Tr);

                if (this.ShowSuminfo)
                {
                    output.AddAttribute(HtmlTextWriterAttribute.Align, "left");  // by bndy at 2008/07/12 10:47
                    output.RenderBeginTag(HtmlTextWriterTag.Td);
                    CreateLeftInfo(output);
                    output.RenderEndTag();
                }

                output.AddAttribute(HtmlTextWriterAttribute.Align, "right");
                output.RenderBeginTag(HtmlTextWriterTag.Td);
                CreateRightInfo(output);
                output.RenderEndTag();

                output.RenderEndTag();
                output.RenderEndTag();
            }
        }


        #region IPostBackEventHandler Implementation
        public void RaisePostBackEvent(string args)
        {
            int pageIndex = this.PageIndex;
            try
            {
                if (string.IsNullOrEmpty(args))
                    args = inputPageIndex;
                pageIndex = int.Parse(args);
            }
            catch { }
            PageChangingEventArgs pcArgs = new PageChangingEventArgs(pageIndex);

            OnPageChanging(pcArgs);
        }

        #endregion

        #region IPostBackDataHandler Implementation

        public virtual bool LoadPostData(string pkey, NameValueCollection pcol)
        {
            string str = pcol[UniqueID + "_input"];
            if (str != null && str.Trim().Length > 0)
            {
                try
                {
                    int pindex = int.Parse(str);
                    if (pindex > 0 && pindex <= PageCount)
                    {
                        inputPageIndex = str;
                        Page.RegisterRequiresRaiseEvent(this);
                    }
                }
                catch { }
            }
            return false;
        }

        public virtual void RaisePostDataChangedEvent() { }

        #endregion

        #region Events

        public event PageChangingEventHandler PageChanging
        {
            add
            {
                Events.AddHandler(EventPageChanging, value);
            }
            remove
            {
                Events.RemoveHandler(EventPageChanging, value);
            }
        }

        public event EventHandler PageChanged
        {
            add
            {
                Events.AddHandler(EventPageChanged, value);
            }
            remove
            {
                Events.RemoveHandler(EventPageChanged, value);
            }
        }

        #endregion

        #region Methods

        protected virtual void OnPageChanging(PageChangingEventArgs e)
        {
            //pageChangeEventHandled = true;
            PageChangingEventHandler handler = (PageChangingEventHandler)Events[EventPageChanging];
            if (handler != null)
            {
                handler(this, e);
                if (!e.Cancel)
                {
                    this.PageIndex = e.NewPageIndex;
                    OnPageChanged(EventArgs.Empty);
                }
            }
            else
            {
                this.PageIndex = e.NewPageIndex;
                OnPageChanged(EventArgs.Empty);
            }
            //pageChangeEventHandled = false;
        }


        protected virtual void OnPageChanged(EventArgs e)
        {
            EventHandler handler = (EventHandler)Events[EventPageChanged];
            if (handler != null)
                handler(this, e);
        }

        #endregion



    }

    #region PageChangingEventHandler Delegate

    public delegate void PageChangingEventHandler(object src, PageChangingEventArgs e);

    #endregion

    #region PageChangingEventArgs Class

    public sealed class PageChangingEventArgs : CancelEventArgs
    {
        private readonly int _newpageindex;


        public PageChangingEventArgs(int newPageIndex)
        {
            _newpageindex = newPageIndex;
        }


        public int NewPageIndex
        {
            get { return _newpageindex; }
        }
    }
    #endregion

    #region Enumerations
    /// <summary>
    /// 跳转页文本框显示方式枚举
    /// </summary>
    public enum PageIndexBox : byte
    {
        /// <summary>
        /// 不显示
        /// </summary>
        Never,
        /// <summary>
        /// 自动显示
        /// </summary>
        Auto,
        /// <summary>
        /// 一直显示
        /// </summary>
        Always
    }

    /// <summary>
    /// 跳转页按钮类型枚举
    /// </summary>
    public enum PageIndexButton
    {
        /// <summary>
        /// 普通按钮
        /// </summary>
        Button,
        /// <summary>
        /// 图片按钮
        /// </summary>
        Image
    }

    /// <summary>
    /// 分页表现形式枚举
    /// </summary>
    public enum PageLayout
    {
        /// <summary>
        /// 层
        /// </summary>
        Div,
        /// <summary>
        /// 表格
        /// </summary>
        Table
    }
    #endregion
}
